﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.FxCop.Sdk;

namespace SinacorRules
{
    public sealed class Rule_DelegateSuffix : BaseAddIn.Rules.BaseRuleFXCop
    {
        #region Constructor

        public Rule_DelegateSuffix()
            : base("DelegateSuffix", "SinacorRules.SinacorRules", typeof(Rule_DelegateSuffix).Assembly)
        {
        }

        #endregion

        #region Public Override Methods

        public sealed override ProblemCollection Check(Member member)
        {
            return CheckDelegate(member);
        }

        #endregion

        #region Private Methods

        private ProblemCollection CheckDelegate(Member member)
        {
            ProblemCollection problemas = new ProblemCollection();
            Field campo = null;
            Method metodo = null;

            if (!member.Name.Name.Contains("$"))
            {
                if (member is Field)
                {
                    campo = (Field)member;

                    if (campo.Type is DelegateNode
                        && campo.Name.Name.ToLower().EndsWith("delegate"))
                    {
                        AddError(campo, "DelegateSuffixResolution", campo.DeclaringType.Name.Name, campo.Name.Name, campo.DeclaringType.Namespace.Name);
                    }
                    else if (campo.Type is ClassNode
                             && Common.Rotinas.CheckClassInheritance((ClassNode)campo.Type, typeof(Delegate))
                             && campo.Name.Name.ToLower().EndsWith("delegate"))
                    {
                        AddError(campo, "DelegateSuffixResolution", campo.DeclaringType.Name.Name, campo.Name.Name, campo.DeclaringType.Namespace.Name);
                    }

                }
                else if (member is Method)
                {
                    metodo = (Method)member;

                    if (metodo.DeclaringType is DelegateNode
                        && metodo.Name.Name.ToLower().EndsWith("delegate"))
                    {
                        AddError(metodo, "DelegateSuffixResolution", metodo.DeclaringType.Name.Name, metodo.Name.Name, metodo.DeclaringType.Namespace.Name);
                    }
                    else
                    {
                        if (metodo.Parameters != null)
                        {
                            foreach (Parameter param in metodo.Parameters)
                            {
                                if (!param.Name.Name.Contains("$")
                                    && param.Name.Name.ToLower().EndsWith("delegate"))
                                {
                                    if (param.Type is DelegateNode)
                                    {
                                        AddError(param, "DelegateSuffixResolution", metodo.DeclaringType.Name.Name, param.Name.Name, metodo.DeclaringType.Namespace.Name);
                                    }
                                    else if (param.Type is ClassNode
                                             && Common.Rotinas.CheckClassInheritance((ClassNode)param.Type, typeof(Delegate)))
                                    {
                                        AddError(param, "DelegateSuffixResolution", metodo.DeclaringType.Name.Name, param.Name.Name, metodo.DeclaringType.Namespace.Name);
                                    }
                                }
                            }
                        }

                        if (metodo.Locals != null)
                        {
                            foreach (Local local in metodo.Locals)
                            {
                                if (!local.Name.Name.Contains("$")
                                    && local.Name.Name.ToLower().EndsWith("delegate"))
                                {
                                    if (local.Type is DelegateNode)
                                    {
                                        AddError(local, "DelegateSuffixResolution", metodo.DeclaringType.Name.Name, local.Name.Name, metodo.DeclaringType.Namespace.Name);
                                    }
                                    else if (local.Type is ClassNode
                                             && Common.Rotinas.CheckClassInheritance((ClassNode)local.Type, typeof(Delegate)))
                                    {
                                        AddError(local, "DelegateSuffixResolution", metodo.DeclaringType.Name.Name, local.Name.Name, metodo.DeclaringType.Namespace.Name);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return base.Problems;
        }

        #endregion
    }
}
